/**
 * 改写原生js数组的'push','pop','shift','unshift','splice','sort','reverse'七个方法,让它能触发响应式
 * 原生js的数组方法都是定义在Array.prototype上的
 */

import { def } from './utils'

// 得到Array.prototype
const arrayPrototype = Array.prototype

// 以Array.prototype为原型创建arrayMethods对象,并暴露出去
export const arrayMethods = Object.create(arrayPrototype)

// 定义要被改写的7个数组方法
const methodsNeedChange = [
  'push',
  'pop',
  'shift',
  'unshift',
  'splice',
  'sort',
  'reverse',
]

methodsNeedChange.forEach((methodName) => {
  // 备份原来的方法，因为push、pop等七个方法的功能不能被剥夺
  const original = arrayPrototype[methodName]

  // 定义新的方法
  def(
    arrayMethods,
    methodName,
    function () {
      // 恢复原来的功能
      const result = original.apply(this, arguments)
      // 把类数组对象变为数组
      const args = [...arguments]
      // 把这个数组的__ob__属性取出来
      const ob = this.__ob__
      // 有三种方法push,unshift,splice三种方法可以添加新项，需要把插入的新项也要变为observe
      let inserted = []
      switch (methodName) {
        case 'push':
        case 'unshift':
          inserted = args
          break
        case 'splice':
          // splice格式为：splice(下标,数量,插入的新项)
          inserted = args.slice(2)
          break
      }

      // 判断有没有要插入的新项
      if (inserted) {
        ob.observeArray(inserted)
      }

      // 发布订阅模式，通知dep
      ob.dep.notify()

      console.log('嘻嘻嘻哈哈哈')
      return result
    },
    false
  )
})
